package il.technion.cs236369.webserver;

import java.net.Socket;
import java.util.HashMap;
import org.apache.http.HttpRequest;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.protocol.HttpContext;

/**
 * A class which holds connection parameters and request details in order to allow the request handler 
 * future treatment of the request open by the socket handlers
 *
 */
public class ExtendedHttpRequest
{
	//This map holds and parameters supplied by the user, in the case a parameter is inserted twice
	//the last version holds
	private HashMap<String,String> parameters = new HashMap<String,String>();
	private String path = null;
	private DefaultHttpServerConnection serverConn = null;
	private HttpRequest httpRequest = null;
	private String type = null;
	private Socket socket;
	
	/** the constructor receives all the connection details (parameters should be added later)
	 * @param socket
	 * @param serverConn
	 * @param httpRequest
	 */
	public ExtendedHttpRequest(Socket socket, 
								DefaultHttpServerConnection serverConn,
								HttpRequest httpRequest)
	{
		this.socket = socket;
		this.serverConn = serverConn;
		this.httpRequest = httpRequest;
		
		if (httpRequest.containsHeader("Cookie"))
		{
			String paramLine = httpRequest.getFirstHeader("Cookie").getValue();
			String[] params = paramLine.split("; ");
			for (String param : params)
			{
				String[] keyValue = param.split("=");
				SetParameter(keyValue[0], keyValue[1]);
			}
		}
	}
	
	//connection attributes
	public DefaultHttpServerConnection GetServerConn() 
	{
		return serverConn;
	}

	public void SetServerConn(DefaultHttpServerConnection serverConn) 
	{
		this.serverConn = serverConn;
	}

	public HttpRequest GetHttpRequest() 
	{
		return httpRequest;
	}

	public void SetHttpRequest(HttpRequest httpRequest) 
	{
		this.httpRequest = httpRequest;
	}

	public String GetPath() 
	{
		if (path == null)
		{
			path = httpRequest.getRequestLine().getUri();
		}
		return path;
	}

	public void SetPath(String path) 
	{
		this.path = path;
		httpRequest.setHeader("REQUEST_URI", path);
	}

	public Socket GetSocket() 
	{
		return socket;
	}

	public void SetSocket(Socket socket) 
	{
		this.socket = socket;
	}
	
	/**
	 * Inserts the given field-value pair in to the parameters map
	 * @param field
	 * @param value
	 */
	public void SetParameter(String field, String value) 
	{
		parameters.put(field, value);
	}
	
	/**
	 * @return a clone of this request parameter map 
	 */
	public HashMap<String,String> GetParameters() 
	{
		@SuppressWarnings("unchecked")
		HashMap<String, String> copy = (HashMap<String, String>) parameters.clone();
		return copy;
	}

	/**
	 * Returns the value mapped to this key or null if doesn't exist
	 * @param key
	 * @return
	 */
	public String GetParameter(String key)
	{
		return parameters.get(key);
	}
	
	public boolean HasParameter(String key)
	{
		return parameters.containsKey(key);
	}
	
	public void SetTypeToPostResponse() 
	{
		type = "POST";
	}

	public void SetTypeToGetResponse() 
	{
		type = "GET";
	}
	
	public String GetType() 
	{
		return type;
	}
	
	/**
	 * Builds an HttpContext from the contained HttpRequest and all it's parameters.
	 * @return
	 */
	public HttpContext GetContext()
	{
		HttpContextImpl context = new HttpContextImpl(GetHttpRequest().getParams());
		context.InsertParams(parameters);
		return context;
	}

}
